#include "EventRecordService.h"
#include "../db/DBPoll.h"
#include "../util/DateTime.h"
#include "../util/TextUtil.h"

// 数据表名称
#define SQL_DB_NAME_RECORD	"t_event_record"

// 建表语句
#define SQL_CREATE_RECORD \
"CREATE TABLE IF NOT EXISTS `t_event_record`("\
"`id` VARCHAR(64) NOT NULL comment '录像编码',"\
"`deviceId` VARCHAR(64) default NULL comment '通道编码',"\
"`deviceName` varchar(64) DEFAULT NULL COMMENT '设备名称',"\
"`eventId` VARCHAR(64) default NULL comment '事件编码',"\
"`eventType` INT(10) default 1 comment '事件类型(进出事件)',"\
"`image` INT(2) default 0 comment '是否图片',"\
"`startTime` DATETIME default NULL comment '开始时间',"\
"`stopTime` DATETIME default NULL comment '结束时间',"\
"`name` VARCHAR(64) default NULL comment '录像名称',"\
"`size` INT(10) default 0 comment '录像大小',"\
"`duration` INT(10) default 0 comment '录像时长',"\
"`path` VARCHAR(255) default NULL comment '录像路径',"\
"`url` VARCHAR(255) default NULL comment '录像地址',"\
"`createTime` DATETIME default NULL comment '添加时间',"\
"`upload` tinyint default 0 comment '上传状态',"\
"`uploadTime` DATETIME default NULL comment '上传时间',"\
"`reserver1` VARCHAR(255) default NULL comment '保留字段1',"\
"`reserver2` VARCHAR(255) default NULL comment '保留字段2',"\
"primary key(`id`),"\
"KEY `idx_event_record_time`(`createTime`)"\
") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='联动录像'"

// SQLite建表
#define SQL_CREATE_RECORD2	\
"CREATE TABLE IF NOT EXISTS `t_event_record`("\
"`id` VARCHAR(64) NOT NULL,"\
"`deviceId` VARCHAR(64) default NULL,"\
"`deviceName` varchar(64) DEFAULT NULL,"\
"`eventId` VARCHAR(64) default NULL,"\
"`eventType` INT(10) default 1,"\
"`image` INT(2) default 0,"\
"`startTime` DATETIME default NULL,"\
"`stopTime` DATETIME default NULL,"\
"`name` VARCHAR(64) default NULL,"\
"`size` INT(10) default 0,"\
"`duration` INT(10) default 0,"\
"`path` VARCHAR(255) default NULL,"\
"`url` VARCHAR(255) default NULL,"\
"`createTime` DATETIME default NULL,"\
"`upload` tinyint default 0,"\
"`uploadTime` DATETIME default NULL,"\
"`reserver1` VARCHAR(255) default NULL,"\
"`reserver2` VARCHAR(255) default NULL,"\
"primary key(`id`)"\
")"

// SQLite创建索引
#define SQL_CREATE_INDEX2 \
"create index IF NOT EXISTS `idx_event_record_time` on `t_event_record`(`createTime`)"

// 新增语句
#define SQL_INSERT_RECORD \
"insert into t_event_record(`id`,`deviceId`,`deviceName`,`eventId`,`eventType`,`image`,"\
"`startTime`,`stopTime`,`name`,`size`,`duration`,`path`,`url`,`createTime`,`upload`) "\
"values('%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', 0)"

// 删除语句					  
#define SQL_DELETE_RECORD \
"delete from t_event_record where `id`='%s'"

// 查询语句					  
#define SQL_QUERY_RECORD \
"select * from t_event_record where `id`='%s'"

// 查询数量					  
#define SQL_QUERY_RECORD_COUNT \
"select count(*) from t_event_record where 1=1"

// 分页查询					  
#define SQL_QUERY_RECORD_PAGE \
"select * from t_event_record where 1=1"

// 更新语句					  
#define SQL_UPDATE_RECORD \
"update t_event_record set `upload` = 1, `uploadTime`='%s' where `id`='%s'"


EventRecordService::EventRecordService()
{
}

EventRecordService::~EventRecordService()
{
}

bool EventRecordService::Exist()
{
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		bool ret = db->IsTableExist(SQL_DB_NAME_RECORD);
		DBPoll::get_mutable_instance().Push(db);
		return ret;
	}
	return false;
}

bool EventRecordService::Create()
{
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		std::string sql = db->GetDbType() == 0 ? SQL_CREATE_RECORD : SQL_CREATE_RECORD2;
		sql = TextUtil::get_mutable_instance().Ascii2Utf8(sql.c_str());
		bool ret = db->CreateTable(sql.c_str());
		DBPoll::get_mutable_instance().Push(db);
		return ret;
	}
	return false;
}

bool EventRecordService::CreateIndex()
{
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		// sqlite
		if (db->GetDbType() == 1)
		{
			std::string sql = SQL_CREATE_INDEX2;
			sql = TextUtil::get_mutable_instance().Ascii2Utf8(sql.c_str());
			bool ret = db->CreateTable(sql.c_str());
			DBPoll::get_mutable_instance().Push(db);
			return ret;
		}
	}
	return true;
}

bool EventRecordService::Add(EventRecordInfo& item)
{
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		std::string sql = boost::str(boost::format(SQL_INSERT_RECORD)
			% item.GetId() % item.GetDeviceId()
			% item.GetDeviceName() % item.GetEventId()
			% item.GetEventType() % item.GetImage()
			% item.GetStartTime().ToNormalString()
			% item.GetStopTime().ToNormalString()
			% item.GetName() % item.GetSize()
			% item.GetDuration() % item.GetPath()
			% item.GetUrl()
			% item.GetCreateTime().ToNormalString());
		uint64_t id = db->Insert(sql.c_str());
		DBPoll::get_mutable_instance().Push(db);
		if (0xffffffff == id)
		{
			return false;
		}
		return true;
	}
	return false;
}

bool EventRecordService::Delete(EventRecordInfo& item, bool delFromDB)
{
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		bool ret = false;
		if (delFromDB)
		{
			std::string sql = boost::str(boost::format(SQL_DELETE_RECORD) % item.GetId());
			ret = db->Delete(sql.c_str());
		}

		DBPoll::get_mutable_instance().Push(db);
		return ret;
	}
	return false;
}

// 查询数量
int EventRecordService::Count()
{
	int count = 0;
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		std::string sql = boost::str(boost::format(SQL_QUERY_RECORD_COUNT));
		bool ret = db->Query(sql.c_str());
		if (ret)
		{
			if (db->FetchNextRow())
			{
				char* v = db->GetColValue(0);
				count = std::stoi(v);
			}
			db->FreeQueryResult();
		}
		DBPoll::get_mutable_instance().Push(db);
	}
	return count;
}

int EventRecordService::Count(std::string deviceId, std::string startTime, std::string endTime, std::string upload)
{
	int count = 0;
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		std::string sql = boost::str(boost::format(SQL_QUERY_RECORD_COUNT));
		if (!deviceId.empty())
		{
			sql += boost::str(boost::format(" and `deviceId`='%s'") % deviceId);
		}
		if (!startTime.empty() && !endTime.empty())
		{
			sql += boost::str(boost::format(" and `createTime` between '%s' and '%s'") % startTime % endTime);
		}
		if (!upload.empty())
		{
			sql += boost::str(boost::format(" and `upload`=%s") % upload);
		}
		bool ret = db->Query(sql.c_str());
		if (ret)
		{
			if (db->FetchNextRow())
			{
				char* v = db->GetColValue(0);
				count = std::stoi(v);
			}
			db->FreeQueryResult();
		}
		DBPoll::get_mutable_instance().Push(db);
	}
	return count;
}

// 查找记录
bool EventRecordService::FindPage(int pageIndex, int pageSize, std::vector<EventRecordInfo>& list)
{
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		std::string sql = boost::str(boost::format(SQL_QUERY_RECORD_PAGE));
		sql += boost::str(boost::format(" limit %d, %d") % pageIndex % pageSize);
		bool ret = db->Query(sql.c_str());
		if (ret)
		{
			while (db->FetchNextRow())
			{
				EventRecordInfo item;
				ToRecord(db, item);
				list.push_back(item);
			}
			db->FreeQueryResult();
		}
		DBPoll::get_mutable_instance().Push(db);
		return ret;
	}
	return false;
}

bool EventRecordService::FindPage(int pageIndex, int pageSize,
	std::string deviceId, std::string startTime,
	std::string endTime, std::string upload,
	std::vector<EventRecordInfo>& list)
{
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		std::string sql = boost::str(boost::format(SQL_QUERY_RECORD_PAGE));
		if (!deviceId.empty())
		{
			sql += boost::str(boost::format(" and `deviceId`='%s'") % deviceId);
		}
		if (!startTime.empty() && !endTime.empty())
		{
			sql += boost::str(boost::format(" and `createTime` between '%s' and '%s'") % startTime % endTime);
		}
		if (!upload.empty())
		{
			sql += boost::str(boost::format(" and `upload`=%s") % upload);
		}
		sql += boost::str(boost::format(" limit %d, %d") % pageIndex % pageSize);
		bool ret = db->Query(sql.c_str());
		if (ret)
		{
			while (db->FetchNextRow())
			{
				EventRecordInfo item;
				ToRecord(db, item);
				list.push_back(item);
			}
			db->FreeQueryResult();
		}
		DBPoll::get_mutable_instance().Push(db);
		return ret;
	}
	return false;
}

bool EventRecordService::Find(EventRecordInfo& item)
{
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		std::string sql = boost::str(boost::format(SQL_QUERY_RECORD) % item.GetId());
		bool ret = db->Query(sql.c_str());
		if (ret)
		{
			ret = false;
			if (db->FetchNextRow())
			{
				ToRecord(db, item);
				ret = true;
			}
			db->FreeQueryResult();
		}
		DBPoll::get_mutable_instance().Push(db);
		return ret;
	}
	return false;
}

bool EventRecordService::Update(EventRecordInfo& item)
{
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		std::string sql = boost::str(boost::format(SQL_UPDATE_RECORD)
			% item.GetUploadTime().ToNormalString()
			% item.GetId());
		bool ret = db->Update(sql.c_str());
		DBPoll::get_mutable_instance().Push(db);
		return ret;
	}
	return false;
}


void EventRecordService::ToRecord(IDbBasePtr db, EventRecordInfo& item)
{
	std::string id = "";
	if (db->GetColValue(0))
	{
		id = db->GetColValue(0);
	}
	std::string deviceId = "";
	if (db->GetColValue(1))
	{
		deviceId = db->GetColValue(1);
	}
	std::string deviceName = "";
	if (db->GetColValue(2))
	{
		deviceName = db->GetColValue(2);
	}
	std::string eventId = "";
	if (db->GetColValue(3))
	{
		eventId = db->GetColValue(3);
	}
	int eventType = 0;
	if (db->GetColValue(4))
	{
		eventType = atoi(db->GetColValue(4));
	}
	int image = 0;
	if (db->GetColValue(5))
	{
		image = atoi(db->GetColValue(5));
	}
	std::string startTime = "";
	if (db->GetColValue(6))
	{
		startTime = db->GetColValue(6);
	}
	std::string stopTime = "";
	if (db->GetColValue(7))
	{
		stopTime = db->GetColValue(7);
	}
	std::string name = "";
	if (db->GetColValue(8))
	{
		name = db->GetColValue(8);
	}
	int size = 0;
	if (db->GetColValue(9))
	{
		size = atoi(db->GetColValue(9));
	}
	int duration = 0;
	if (db->GetColValue(10))
	{
		duration = atoi(db->GetColValue(10));
	}
	std::string path = "";
	if (db->GetColValue(11))
	{
		path = db->GetColValue(11);
	}
	std::string url = "";
	if (db->GetColValue(12))
	{
		url = db->GetColValue(12);
	}
	std::string createTime = "";
	if (db->GetColValue(13))
	{
		createTime = db->GetColValue(13);
	}
	int upload = 0;
	if (db->GetColValue(14))
	{
		upload = atoi(db->GetColValue(14));
	}
	std::string uploadTime = "";
	if (db->GetColValue(15))
	{
		uploadTime = db->GetColValue(15);
	}

	item.SetId(id);
	item.SetDeviceId(deviceId);
	item.SetDeviceName(deviceName);
	item.SetEventId(eventId);
	item.SetEventType(eventType);
	item.SetImage(image);

	DateTime start_time;
	start_time.From(startTime);
	item.SetStartTime(start_time);

	DateTime stop_time;
	stop_time.From(stopTime);
	item.SetStopTime(stop_time);

	item.SetName(name);
	item.SetSize(size);
	item.SetDuration(duration);
	item.SetPath(path);
	item.SetUrl(url);

	DateTime create_time;
	create_time.From(createTime);
	item.SetCreateTime(create_time);

	item.SetUpload(upload);

	DateTime upload_time;
	upload_time.From(uploadTime);
	item.SetUploadTime(upload_time);
}
